/*
 * $Id: verify.c,v 1.14 1995/03/30 22:19:37 chris Exp $
 */

#include <stdio.h>
#include <ctype.h>
#include "atom.h"
#include "dtd.h"
#include "html.h"
#include "entity.h"

static void dump_tree(struct block *top, int depth);
static printtext(char *str);
static printattr(char *str, char quote);

static int allclose = 1;	/* Current print all optional close tags */

main(int ac, char *argv[])
{
    struct block *bp;
    extern FILE *yyin;

    if (ac > 1) {
	yyin = fopen(argv[1], "r");
	if (yyin == NULL) {
	    perror(argv[1]);
	    exit (1);
	}
    }
    HTMLParseBegin();
    HTMLParseDo(yyin);
    bp = HTMLParseEnd();
    dump_tree(bp, 0);
    HTMLFreeParseTree(bp);
    exit(0);
}

void
dump_tree(struct block *top, int depth)
{
    struct block *cur;
    /* Print out block data */
    if (depth != 0) { 		/* Ignore top block data */
	if (top->type == TAG) {
	    fprintf(stdout, "<%s", GetAtomVal(top->bAtom));
	    /* print out any attributes */
	    if (top->attrs) {
		struct attribute *ap = top->attrs;

		while (ap) {
		    fprintf(stdout, " %s", ap->name);
		    if (ap->data) {
			if (ap->flags & DQUOTEDVALUE) {
			    fprintf(stdout, "=\"");
			    printattr(ap->data, '"');
			    fprintf(stdout, "\"");
			}
			else if (ap->flags & SQUOTEDVALUE) {
			    fprintf(stdout, "='");
			    printattr(ap->data, '\'');
			    fprintf(stdout, "'");
			}
			else {
			    fprintf(stdout, "=%s", ap->data);
			}
		    }
		    ap = ap->next;
		}
	    }
	    if (top->flags & PRETTYSTART)
		fprintf(stdout, ">\n");
	    else
		fprintf(stdout, ">");
	}
	else if (top->type == CMNT) {
	    fprintf(stdout, "<!--%s-->\n", top->data);
	}
	else if (top->type == DOCTYPE) {
	    fprintf(stdout, "<!DOCTYPE %s>\n", top->data);
	}
	else {
	    printtext(top->data);		/* PCDATA */
	    if (top->flags & PRETTYSTART)
		fprintf(stdout, "\n");
	}
    }
    /* Print out children */
    cur = top->children;
    while (cur) {
	dump_tree(cur, depth + 1);
	cur = cur->next_sib;
    }
    /* Print out terminator (if applicable) */
    if ((top->type == TAG) && (IsEleNoneTermed(top->bAtom) == 0)) {
	if (HTMLGetBFlags(top) & SHRTTAG)
	    fprintf(stdout, "<//>");
	else if (((HTMLGetBFlags(top) & OPTCLOSE) == 0) || allclose)
	    fprintf(stdout, "</%s>", GetAtomVal(top->bAtom));
	if (top->flags & PRETTYEND)
	    fprintf(stdout, "\n");
    }
}

/*
 * Print out character text with eight byte text using entities
 */
static
printtext(char *str)
{
    while (*str) {
	if (*str & 0x80) {
	    char *nstr = GetEntityName(*str);

	    if (nstr)
		fprintf(stdout, "&%s;", nstr);
	    else
		fprintf(stdout, "&%d;", (int)*str);
	}
	else {
	    switch (*str) {
		case '<':
		    fprintf(stdout, "&lt;");
		    break;
		case '>':
		    fprintf(stdout, "&gt;");
		    break;
		case '&':
		    fprintf(stdout, "&amp;");
		    break;
		default:
		    putc(*str, stdout);
		    break;
		}
	}
	str++;
    }
}

/*
 * Print out quoted attribute text with eight byte text using entities
 */
static
printattr(char *str, char quote)
{
    while (*str) {
	if (*str & 0x80) {
	    char *nstr = GetEntityName(*str);

	    if (nstr)
		fprintf(stdout, "&%s;", nstr);
	    else
		fprintf(stdout, "&%d;", (int)*str);
	}
	else {
	    switch (*str) {
		case '<':
		    fprintf(stdout, "&lt;");
		    break;
		case '>':
		    fprintf(stdout, "&gt;");
		    break;
		case '&':
		    fprintf(stdout, "&amp;");
		    break;
		case '"':
		    if (quote == '"')
			fprintf(stdout, "&quot;");
		    else
			putc(*str, stdout);
		    break;
		case '\'':
		    if (quote == '\'')
			fprintf(stdout, "&39;");
		    else
			putc(*str, stdout);
		    break;
		default:
		    putc(*str, stdout);
		    break;
	    }
	}
	str++;
    }
}
